package controllers

import (
	"encoding/json"
	"github.com/astaxie/beego/logs"
	"io"
	"net/http"
	services "tinyrdm/backend/services"
	"tinyrdm/backend/types"
)

var preferencesLog = logs.GetLogger("Preferences")

type PreferencesController struct {
	BaseController
	clientVersion string
}

type PrefReqData struct {
	Method string `json:"method"`

	X int `json:"x"`
	Y int `json:"y"`

	Width     int  `json:"width"`
	Height    int  `json:"height"`
	Maximised bool `json:"maximised"`

	Ver string `json:"ver"`

	Preferences types.Preferences `json:"preferences"`

	Values map[string]any `json:"values"`
}

var preferences = services.Preferences()

func (c *PreferencesController) Handler() {
	var req PrefReqData
	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
	if err != nil {
		logs.Error(err, string(c.Ctx.Input.RequestBody))
		c.ErrorJson(err)
		return
	}
	var resp any
	switch req.Method {
	case "Start":

		break
	case "CheckForUpdate":
		resp = c.checkForUpdate()
		break
	case "GetAppVersion":
		resp = c.getAppVersion()
		break
	case "GetBuildInDecoder":
		resp = preferences.GetBuildInDecoder()
		break
	case "GetDecoder":
		resp = preferences.GetDecoder()
		break
	case "GetFontList":
		resp = preferences.GetFontList()
		break
	case "GetPreferences":
		resp = preferences.GetPreferences()
		break
	case "GetScanSize":
		resp = preferences.GetScanSize()
		break
	case "GetWindowPosition":
		//resp = preferences.GetWindowPosition()
		break
	case "GetWindowSize":
		w, h, m := preferences.GetWindowSize()
		resp = map[string]any{
			"width":     w,
			"height":    h,
			"maximised": m,
		}
		break
	case "RestorePreferences":
		resp = preferences.RestorePreferences()
		break
	case "SaveWindowPosition":
		preferences.SaveWindowPosition(req.X, req.Y)
		break
	case "SaveWindowSize":
		preferences.SaveWindowSize(req.Width, req.Height, req.Maximised)
		break
	case "SetAppVersion":
		c.clientVersion = req.Ver
		preferences.SetAppVersion(req.Ver)
		break
	case "SetPreferences":
		resp = preferences.SetPreferences(req.Preferences)
		break
	case "UpdatePreferences":
		resp = preferences.UpdatePreferences(req.Values)
		break
	default:
		resp = types.JSResp{
			Success: false,
			Msg:     "未找到该方法",
			Data:    nil,
		}
		preferencesLog.Printf("not found: %s", req.Method)
	}
	if resp == nil {
		resp = types.JSResp{
			Success: true,
			Msg:     "Successful",
			Data:    nil,
		}
	}
	c.postJson(resp)
}

type latestRelease struct {
	Id      int    `json:"id"`
	TagName string `json:"tag_name"`
	Assets  []any  `json:"assets"`
}

func (c *PreferencesController) checkForUpdate() (resp types.JSResp) {
	// request latest version
	res, err := http.Get("https://gitee.com/api/v5/repos/tuonina/tiny-rdm-server/releases/latest")
	if err != nil || res.StatusCode != http.StatusOK {
		resp.Msg = "network error"
		return
	}
	text, err := io.ReadAll(res.Body)
	var respObj latestRelease
	err = json.Unmarshal(text, &respObj)
	if err != nil {
		resp.Msg = "invalid content"
		logs.Warn("decode fail", err, string(text))
		return
	}
	preferences.GetAppVersion()

	// compare with current version
	resp.Success = true
	resp.Data = map[string]any{
		"version":  c.clientVersion,
		"latest":   respObj.TagName,
		"page_url": "https://gitee.com/tuonina/tiny-rdm-server/releases",
	}
	return
}

func (c *PreferencesController) getAppVersion() (resp types.JSResp) {
	resp.Success = true
	resp.Data = map[string]any{
		"version": c.clientVersion,
	}
	return
}

func (c *PreferencesController) SetAppVersion(ver string) {
	c.clientVersion = ver
	preferences.SetAppVersion(ver)
}
